/**
 * 
 */
package com.ddf.exception;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.ddf.util.Constants;

/**
 * 用于处理全局异常的一个类，支持国际化，标准请抛出GlobalCustomizeException，
 * 其参数需要在 com.sinotrans.hd.dev.exception.GlobalExceptionEnum 中配置，
 * 对应的消息文件在exception.properties所处Locale中配置
 * 附加配合Log4j记录单独记录异常日志到文件中
 * @author DDF 2017年11月28日
 *
 */
@Component
public class GlobalExceptionHandler implements HandlerExceptionResolver {
	@Autowired
	private MessageSource messageSource;
	/** 异常日志 */
	private static Logger log = LoggerFactory.getLogger("exceptionLog");
	/** 资源文件baseName */
	// private static final String EXCEPTION_RESOURCE_BASE_NAME = "exception";

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		try {
			request.setCharacterEncoding(Constants.CHARSET_U8);
			log.info("RequestMapping [{}] progress start.......", request.getServletPath());
			if (Constants.isNotNull(request.getQueryString())) {
				log.info("QueryString: [{}]", URLDecoder.decode(request.getQueryString(), Constants.CHARSET_U8));
			}
		} catch (UnsupportedEncodingException e1) {
			log.error(e1.getMessage());
		} finally {
			ModelAndView mv = new ModelAndView();
			GlobalCustomizeException exception = null;
			String codeKey = "";
			String codeValue = "";
			if (ex instanceof GlobalCustomizeException) {
				// 对抛出的异常进行定制化消息处理
				exception = (GlobalCustomizeException) ex;
				Locale locale = request.getLocale();
				codeKey = exception.getMessage();
				codeValue = messageSource.getMessage(codeKey, exception.getParams(), codeKey, locale);
				// JDK自带的国际化支持写法
				/*ResourceBundle resourceBundle = ResourceBundle.getBundle(EXCEPTION_RESOURCE_BASE_NAME, locale);
				if (resourceBundle != null && resourceBundle.containsKey(codeKey)) {
					codeValue = resourceBundle.getString(codeKey);
					if (Constants.isNotNull(exception.getParams())) {
						MessageFormat mf = new MessageFormat(codeValue, locale);
						codeValue = mf.format(exception.getParams());
					}
				} else {
					codeValue = codeKey;
				}*/
			} else if (ex instanceof DataException) {
				// 兼容原框架抛出的DataException
				exception = new GlobalCustomizeException(ex.getMessage());
				codeKey = ex.getMessage();
				codeValue = ex.getMessage();
			} else {
				// 可对运行时异常在资源文件中进行定制化消息，如果不定义的话，直接返回原错误信息
				exception = new GlobalCustomizeException(ex.toString());
				Locale locale = request.getLocale();
				codeKey = exception.getMessage();
				codeValue = messageSource.getMessage(codeKey, exception.getParams(), codeKey, locale);
			}
			/** 
			 * 配合log4j的日志管理将异常信息输出到文件中
			 * ------------------------------异常日志start----------------------- 
			 */
			StringWriter sw = new StringWriter();
			PrintWriter errorPw = new PrintWriter(sw);
			ex.printStackTrace(errorPw);
			Object []logMessage = null;
			// 把解析后的消息附加上
			if (Constants.isNotNull(codeKey) && !codeKey.equals(codeValue)) {
				logMessage = new Object[] {
					/*((Map<String, Object>) SecurityUtils.getSubject().getSession().
							getAttribute("user")).get("LOGIN_NAME"),*/
					codeValue,
					sw.toString()
				};
			} else {
				logMessage = new Object[] {
					/*((Map<String, Object>) SecurityUtils.getSubject().getSession().
							getAttribute("user")).get("LOGIN_NAME"),*/
					sw.toString()
				};
			}
			// 异常日志记录异常消息
			log.error("currUser: {}, {}, message: {}", logMessage);
			/** ------------------------------异常日志start----------------------- */
			log.info("RequestMapping [{}] progress end.......", request.getServletPath());
			StringBuilder sbl = new StringBuilder();
			// 将错误信息返回前端
			response.setStatus(500); 
			response.setContentType("text/html;charset=UTF-8");
			sbl.append("{").append("\"code\": \"").append(codeKey).append("\", \"")
			   .append("message\": \"").append(codeValue).append("\"}");
			mv.addObject("message", sbl.toString());
			mv.setViewName("");
			PrintWriter pw = null;
			try {
				pw = response.getWriter();
				pw.write(sbl.toString());
			} catch (IOException e) {
				log.error(e.getMessage());
			} finally {
				if (pw != null) {
					pw.close();
				}
			}
		}
		return null;
	}  

}
